"""
文件 | 接口
"""

from fastapi import (
    APIRouter,
    Depends,
)

import utils.enum_utils as enum
from biz import file_biz
from components.audit_log import audit
from components.depends import login_required
from components.global_param import get_user_id
from components.logger import log
from components.response import (
    FileDownloadResponse,
    FileViewResponse,
    OKResponse,
    OKWithDataResponse,
)
from models import OK
from models.other import FileStream
from models.request import (
    FileBatchDownloadRequest,
    FileDetailRequest,
    FileListRequest,
    FilePathField,
    FileUpdateRequest,
    FileUploadRequest,
)
from models.response import (
    FileBatchDownloadResponse,
    FileDetailResponse,
    FileListResponse,
)
from models.vo import (
    FileBatchDownloadVO,
    FileDetailVO,
    FileListPage,
)
from utils.data_utils.special import ObjectIdStr

file_router: APIRouter = APIRouter(prefix="/file")
""" 文件 路由 """


@file_router.post(
    path="/upload/",
    summary="文件 | 上传",
    response_model=FileDetailResponse,
    dependencies=[Depends(login_required)],
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.UPLOAD,
    po_id="response.data.file_id",
)
async def file_upload(
    request: FileUploadRequest = Depends(FileUploadRequest.as_form),
) -> OKWithDataResponse:
    vo: FileDetailVO = file_biz.FileUploader.upload(request)
    log.info(f"[文件][上传] user_id: {get_user_id()} file_id: {vo.file_id}")

    return OKWithDataResponse(vo)


@file_router.delete(
    path="/{file_id}/",
    summary="文件 | 删除",
    response_model=OK,
    dependencies=[Depends(login_required)],
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.DELETE,
    po_id="file_id",
)
async def file_delete(file_id: ObjectIdStr = FilePathField.file_id) -> OKResponse:
    request = FileDetailRequest(file_id=file_id)
    file_biz.FileDeleter.delete(request)
    log.info(f"[文件][删除] user_id: {get_user_id()} file_id: {file_id}")

    return OKResponse()


@file_router.put(
    path="/{file_id}/",
    summary="文件 | 更新",
    response_model=FileDetailResponse,
    dependencies=[Depends(login_required)],
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.UPDATE,
    po_id="file_id",
)
async def file_update(
    request: FileUpdateRequest,
    file_id: ObjectIdStr = FilePathField.file_id,
) -> OKWithDataResponse:
    request.file_id = file_id
    vo: FileDetailVO = file_biz.FileUpdator.update(request)
    log.info(f"[文件][更新] user_id: {get_user_id()} file_id: {file_id}")

    return OKWithDataResponse(vo)


@file_router.get(
    path="/{file_id}/",
    summary="文件 | 详情",
    response_model=FileDetailResponse,
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.DETAIL,
    po_id="file_id",
)
async def file_detail(file_id: ObjectIdStr = FilePathField.file_id) -> OKWithDataResponse:
    request = FileDetailRequest(file_id=file_id)
    vo: FileDetailVO = file_biz.FileGetter.detail(request)
    log.info(f"[文件][详情] user_id: {get_user_id()} file_id: {file_id}")

    return OKWithDataResponse(vo)


@file_router.get(
    path="/",
    summary="文件 | 列表",
    response_model=FileListResponse,
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.LIST,
    po_id="response.data.data_list.file_id",
)
async def file_list(request: FileListRequest = Depends(FileListRequest.from_query)) -> OKWithDataResponse:
    vo: FileListPage = file_biz.FileGetter.list(request)
    log.info(f"[文件][列表] user_id: {get_user_id()}")

    return OKWithDataResponse(vo)


@file_router.get(
    path="/{file_id}/download/",
    summary="文件 | 下载",
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.DOWNLOAD,
    po_id="file_id",
)
async def file_download(file_id: ObjectIdStr = FilePathField.file_id) -> FileDownloadResponse:
    request = FileDetailRequest(file_id=file_id)
    file_stream: FileStream = file_biz.FileGridGetter.get_file_grid(request)
    log.info(f"[文件][下载] user_id: {get_user_id()} file_id: {file_id}")

    return FileDownloadResponse(file_stream)


@file_router.get(
    path="/{file_id}/view/",
    summary="文件 | 预览",
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.VIEW,
    po_id="file_id",
)
async def file_view(file_id: ObjectIdStr = FilePathField.file_id) -> FileViewResponse:
    request = FileDetailRequest(file_id=file_id)
    file_stream: FileStream = file_biz.FileGridGetter.get_file_grid(request)
    log.info(f"[文件][预览] user_id: {get_user_id()} file_id: {file_id}")

    return FileViewResponse(file_stream)


@file_router.post(
    path="/download/batch/",
    summary="文件 | 批量下载",
    response_model=FileBatchDownloadResponse,
    dependencies=[Depends(login_required)],
)
@audit(
    model=enum.Model.FILE,
    operation=enum.ModelOperation.DOWNLOAD,
    po_id="request.file_id_list",
)
async def file_download_batch(request: FileBatchDownloadRequest) -> OKWithDataResponse:
    vo: FileBatchDownloadVO = file_biz.FileBatchDownloadHandler.batch_download(request)
    log.info(f"[文件][批量下载] user_id: {get_user_id()} file_id_list: {request.file_id_list}")

    return OKWithDataResponse(vo)
